/*********************************************************************/
// visStreamsurface.h
 /* Initially, my design is that the class visStreamsurface inherits 
  * from the class visStreamline. But later, it's seen that there are 
  * considerable differeces betweens them, especially in the aspect of
  * setting sources. Hence, this class visStreamsurface ensued.
 
  * The program constructs a series of streamsurface in the flow field
  */

 /* Given the data field, there are four different ways to specify the 
  * seed sources in it : 
  * 1. a string of points;
  * 2. a line segment(specified by two points) which will be devided;
  * 3. multiple strings of points;
  * 4. and multiple line segments.
  
  * Anyhow, one set of points is a source for streamlines, that is, from 
  * these points streamlines are first generated, and then adjacent two
  * streamlines are bridged by something like triangles to form a whole
  * streamsurface.
 */ 

/*******************************************lu, xinlai 2008/5/8********
**********************************************************************/

#ifndef VIS_STREAM_SURFACE
#define VIS_STREAM_SURFACE

#include "visStreamline.h"

namespace visualization
{
/* The streamsurface class
*/
//=====================
class visStreamsurface
//=====================
{
public:
	/* Constructor
	*/
	//==========================================
	visStreamsurface(visualization::Model *mdl)
	//==========================================
	{

		dataField = mdl;
		makeCircle = 0;
		integrationDirection = 0;
		ratio = 1.5;
		// Allocate memory for triangles which should be released
		// by programs invoking visStreamsurface.
		triangles = new vector<Point>;
	}

	/* Destructor
	*/
	//======================
	~visStreamsurface()
	{
		// Apparently release memory for streamlines in the variable streamsurface.
//		for(int i = 0; i < nStreamsurface; i++)
//		{
//			streamsurface[i].releaseStreamlines();
//		}
//		// Delete streamsurface
//		delete []streamsurface;
//		streamsurface = NULL;
	}
	
	// Apparently release the memory for triangles
	void releaseTriangles()
	{
	  delete triangles;
		triangles = NULL;
	}
	//======================

	/* Set the ratio used when two streamlines 
	 * are to be bridged by triangles.

	 * Streamlines forming streamsurface may be 
	 * divergent or too close, therefor, a mesure
	 * should be employed to indicate when it's
	 * necessary to split or merge the streamsurface.
	 * ratio is simply for this purpose.
	*/
	//=====================
	void setRatio(int rto)
	//=====================
	{
		ratio = rto;
	}

/* The following four funcitons are for setting streamsurface sources.
 * It should be noted that at one time only one of them can be used.
*/	

    /************************************************************
	Set a string of points from which streamlins will begin
	to grow. To support multiple streamsurfaces, a set of these 
	strings should be supported.
	************************************************************/
	/* pointsNum : the number of streamsurfaces that 
	   are supposed to be generated.     
     * sources : the sources, an array of size pointsNum.
	*/
	//====================================
	void setPointSources(int pointsNum,
						 double sources[]
						 );
	//====================================
	
	/* surfaceNum : the number of streamsurfaces that are 
	   supposed to be generated.
     * stlInOneSurface : each element gives the number of
	   points that will be the starting points of streamlines.
     * sources : the sources, an array of size (surfaceNum * 
	   stlInOneSurface) by 3, with 3 doubles in each line 
	   representing the coordinates of a point.
	*/
    /* Each string of points, which will form streamsurface,
	 * will go to the array streamsurface. So, it's also 
	 * needed to initialize the variable streamsurface.
	*/


    // changed ++++++++++++++++++++++++++++++++++
	//=================================================
	void setMultiplePointSources1(int surfaceNum,
								 int stlInOneSurface[],
								 double **sources);
	//=================================================

	//=================================================
	void setMultiplePointSources2(int surfaceNum,
								 int commonNumber,
								 double **sources);
	//=================================================

	/*
	*/
	//==================================
	void setLineSources(int surfaceNum,
    	                double *sourceX,
						double *sourceY
						);
	//==================================

	/*
	*/
	//=============================
	void setMultipleLineSources();
	//=============================

/*************The following is similar to these in visStreamline**********/

	/* Whether to make the sources form a circle.
	 * This processes all the surface in streamsurfaces.
	*/
	//===========================
	void makeSourcesFormCircle();
	//===========================

/* These three functions set the integration directions.
 * These process all the surface in streamsurfaces.
*/
	void setIntegrationForward();
	void setIntegrationBackward();
	void setIntegrationDouble();

/* The step goes to the variable of visRungeKutta4, 
 * and the maxPrpgtTime controls the propagation time.

 * This processes all the surface in streamsurfaces.
*/
//==========================================
	void setParameters(double step,
					   double maxPrpgtTime);
//==========================================

/*************************************************************************/






	/* Construct the triangles bridging two streamlines
	 * This is implemented recursively
	 * sl1		 : streamline 1
	 * startInd1 : where to begin in sl1
	 * sl2		 : streamline 2
	 * startInd2 : where to begin in sl2
	 * triIndex	 : the index of the triangles in which the current
	 *             strip is stored
    */
	//==============================================================
	inline void bridgeTwoStreamLine(vector<visualization::Point> *sl1,
									unsigned startIndex1,
		                            vector<visualization::Point> *sl2,
									unsigned startIndex2,
									int &triIndex,
									int startingPointOrNot
									);
	//==============================================================

	/* Constuct the streamsurface
	 * For each pair of streamlines in streamlines(visStreamline.h),
	 * construct the ribbon and save the result to triangles
	*/
	//=============================
	void constructStreamSurface();
	//=============================

	/* Get the constructed surface
	*/
	vector<visualization::Point> *getTheStreamSurface()
	{
		return triangles;
	}

	/*
	*/
	//=========================================================
	double pointsDist(vector<visualization::Point> *sl1,
					  unsigned startIndex1,
					  vector<visualization::Point> *sl2,
					  unsigned startIndex2);
	//=========================================================

	/*
	*/
	//====================================================
	int longerDiagonal(vector<visualization::Point> *sl1,
					   unsigned startIndex1,
					   vector<visualization::Point> *sl2,
					   unsigned startIndex2);
	//====================================================

protected:
	/* This defines the data field where streamsurfaces are 
	 * going to be generated.
	*/
	visualization::Model *dataField;

	/* The variable storing streamsurfaces.
	 * Since multiple streamsurfaces are supposed to be allowed 
	 * and one of them can be realized by the class vsiStreamline,
	 * so all of the streamsurface is an array of the class
	 * vsiStreamline.
	*/
	visStreamline *streamsurface;

	int nStreamsurface;
	int *streamlinesInOneSurface;
	int integrationDirection;
	int makeCircle;

	double stepSize, maxPropagationTime;

	/* The triangles bridging two adjacent streamlines should be 
	 * saved. In the first version, this is done as below:
	   
	   vector<vector<visualization::Point>> triangles;

     * This actually causes problems. It's proved that when two or
	 * more points are contiguously selected from the same streamline ,
	 * then a hole ensues.

	 * The solution is to save the triangles by saving their vertices.
    */
	vector<Point> *triangles;

	// The maximum distance that can be tolorated between 
	// two points on two streamlines respectively
	double maxDist;

	// The minimum distance that can be tolorated between 
	// two points on two streamlines respectively
	double minDist;

	// The ratio of the current distance to maxDist or minDist,
	// depending on which,it can be decided whether to continue
	// the current ribbon,or split it,or merge two of them(in face,
	// the program doesn't merge them, instead it cuts the density
	// of the triangles,which results in the same effect)
	double ratio;

	//
	int directionFlag;
};

}
#endif

